package org.gdstash.ui.stash;

import org.gdstash.character.GDChar;
import org.gdstash.character.GDCharInventorySack;
import org.gdstash.item.GDAbstractContainer;
import org.gdstash.item.GDItem;
import org.gdstash.ui.GDStashFrame;
import org.gdstash.ui.GDUITransfer;
import org.gdstash.ui.util.AdjustablePanel;
import org.gdstash.ui.util.GDCharInfoList;
import org.gdstash.util.GDConstants;
import org.gdstash.util.GDImagePool;
import org.gdstash.util.GDMsgFormatter;
import org.gdstash.util.GDMsgLogger;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public class GDCharStashPane extends AdjustablePanel implements GDUIInventory {
    public static final int OFFSET_X_STASH_CHAR = 117;
    public static final int OFFSET_Y_STASH_CHAR = 99;
    public static final int OFFSET_X_STASH_CHAR_TAB = 97;
    public static final int OFFSET_Y_STASH_CHAR_TAB = 100;
    private static final int OFFSET_X_EQUIPPED_CHAR = 19;
    private static final int OFFSET_Y_EQUIPPED_CHAR = 33;
    private static final int OFFSET_X_INVENTORY_CHAR = 86;
    private static final int OFFSET_Y_INVENTORY_CHAR = 485;
    private static final int OFFSET_X_BAG_1_CHAR = 15;
    private static final int OFFSET_Y_BAG_1_CHAR = 0;
    private static final int OFFSET_X_BAG_2_CHAR = 287;
    private static final int OFFSET_Y_BAG_2_CHAR = 0;
    private static final int OFFSET_X_BAG_3_CHAR = 15;
    private static final int OFFSET_Y_BAG_3_CHAR = 261;
    private static final int OFFSET_X_BAG_4_CHAR = 287;
    private static final int OFFSET_Y_BAG_4_CHAR = 261;
    private static final int OFFSET_X_BAG_5_CHAR = 15;
    private static final int OFFSET_Y_BAG_5_CHAR = 521;
    private GDStashFrame frame;
    private JTabbedPane tabPages;
    private GDContainerMapPane[] pnlPages;
    private JComboBox<String> cbSelChar;
    private GDCharInfoList.GDCharFileInfo info;
    private GDItem selItem;
    private GDContainerMapPane selPage;
    private JPanel pnlMain;
    private GDUITransfer uiTransfer;

    public GDCharStashPane(final GDStashFrame frame, final GDUITransfer uiTransfer) {
        this.frame = frame;
        this.uiTransfer = uiTransfer;
        this.pnlPages = new GDContainerMapPane[3];
        this.selItem = null;
        this.selPage = null;
        this.adjustUI();
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        this.pnlMain = this.buildMainPanel();
        layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(this.pnlMain));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(this.pnlMain));
        layout.setVerticalGroup(vGroup);
    }

    @Override
    public void adjustUI() {
        final Font fntLabel = UIManager.getDefaults().getFont("Label.font");
        Font fntCombo = UIManager.getDefaults().getFont("ComboBox.font");
        if (fntCombo == null) {
            fntCombo = fntLabel;
        }
        Font fntTabbed = UIManager.getDefaults().getFont("TabbedPane.font");
        if (fntTabbed == null) {
            fntTabbed = fntLabel;
        }
        fntCombo = fntCombo.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        fntTabbed = fntTabbed.deriveFont((float) GDStashFrame.iniConfig.sectUI.fontSize);
        GDChar gdc = null;
        if (this.info != null) {
            gdc = this.info.gdChar;
        }
        if (this.pnlPages[0] == null) {
            this.pnlPages[0] = new GDPrivateStashPane(gdc, this.frame, this, this.uiTransfer);
            if (gdc != null) {
                final List<GDAbstractContainer> list = gdc.getStashPages();
                for (final GDAbstractContainer page : list) {
                    final GDContainerPane container = new GDContainerPane(3, 0, 0, this.frame, this, this.uiTransfer);
                    container.setContainer(page);
                    this.pnlPages[0].addContainer(container);
                }
            }
        }
        if (this.pnlPages[1] == null) {
            this.pnlPages[1] = new GDContainerMapPane(this, this.uiTransfer, GDImagePool.getCharStashBG());
            final GDUIContainer container2 = new GDEquippedContainerPane(19, 33, this.frame, this, this.uiTransfer);
            final GDUIContainer container3 = new GDContainerPane(4, 86, 485, this.frame, this, this.uiTransfer);
            if (gdc != null) {
                container2.setContainer(gdc.getEquipment());
                container3.setContainer(gdc.getInventory());
            }
            this.pnlPages[1].addContainer(container2);
            this.pnlPages[1].addContainer(container3);
        }
        if (this.pnlPages[2] == null) {
            this.pnlPages[2] = new GDContainerMapPane(this, this.uiTransfer, GDImagePool.getCharStashBG());
            this.buildBagContainer(gdc);
        }
        if (this.tabPages == null) {
            (this.tabPages = new JTabbedPane()).setTabPlacement(1);
        }
        this.tabPages.removeAll();
        this.tabPages.add(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_CHAR_STASH"), this.pnlPages[0]);
        this.tabPages.add(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_CHAR_INVENTORY"), this.pnlPages[1]);
        this.tabPages.add(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_CHAR_BAGS"), this.pnlPages[2]);
        this.tabPages.setFont(fntTabbed);
        this.tabPages.setMaximumSize(new Dimension(this.pnlPages[0].getPreferredWidth(), this.pnlPages[0].getPreferredHeight() + 20));
        if (this.cbSelChar == null) {
            (this.cbSelChar = new JComboBox<String>()).addActionListener(new CharSelectActionListener());
        }
        final int idx = this.cbSelChar.getSelectedIndex();
        this.cbSelChar.removeAllItems();
        final String[] entries = GDCharInfoList.getCharInfos();
        for (int i = 0; i < entries.length; ++i) {
            this.cbSelChar.addItem(entries[i]);
        }
        if (idx != -1) {
            this.cbSelChar.setSelectedIndex(idx);
        }
        this.cbSelChar.setFont(fntCombo);
        this.cbSelChar.setMaximumSize(new Dimension(1000, 3 * GDStashFrame.iniConfig.sectUI.fontSize));
    }

    @Override
    public void refresh() {
        if (this.pnlPages[0] != null) {
            this.pnlPages[0].refresh();
        }
        if (this.pnlPages[1] != null) {
            this.pnlPages[1].refresh();
        }
        if (this.pnlPages[2] != null) {
            this.pnlPages[2].refresh();
        }
    }

    private JPanel buildMainPanel() {
        GroupLayout layout = null;
        GroupLayout.SequentialGroup hGroup = null;
        GroupLayout.SequentialGroup vGroup = null;
        final JPanel panel = new JPanel();
        this.layoutStash();
        layout = new GroupLayout(panel);
        panel.setLayout(layout);
        layout.setAutoCreateGaps(true);
        layout.setAutoCreateContainerGaps(true);
        hGroup = layout.createSequentialGroup();
        hGroup.addGroup(layout.createParallelGroup().addComponent(this.cbSelChar).addComponent(this.tabPages));
        layout.setHorizontalGroup(hGroup);
        vGroup = layout.createSequentialGroup();
        vGroup.addGroup(layout.createParallelGroup().addComponent(this.cbSelChar)).addGroup(layout.createParallelGroup().addComponent(this.tabPages));
        layout.setVerticalGroup(vGroup);
        layout.linkSize(0, this.cbSelChar, this.tabPages);
        return panel;
    }

    public void updateConfig() {
        if (this.pnlPages != null) {
            for (final GDContainerMapPane page : this.pnlPages) {
                page.updateConfig();
            }
        }
    }

    public void initCharSelection() {
        this.cbSelChar.removeAllItems();
        this.cbSelChar.addItem("");
        for (final GDCharInfoList.GDCharFileInfo info : GDCharInfoList.gdCharFileInfos) {
            this.cbSelChar.addItem(info.charInfo);
        }
    }

    public void refreshCharSelection() {
        File file = null;
        if (this.info != null) {
            file = this.info.charFile;
        }
        this.cbSelChar.removeAllItems();
        this.cbSelChar.addItem("");
        GDCharInfoList.GDCharFileInfo selInfo = null;
        int idx = -1;
        int i = 1;
        for (final GDCharInfoList.GDCharFileInfo info : GDCharInfoList.gdCharFileInfos) {
            this.cbSelChar.addItem(info.charInfo);
            if (info.charFile.equals(file)) {
                selInfo = info;
                idx = i;
            }
            ++i;
        }
        if (idx == -1) {
            this.setChar(null);
        } else {
            this.cbSelChar.setSelectedIndex(idx);
        }
    }

    public void renameCharDir(final File fDirOld, final File fDirNew) {
        if (this.info == null) {
            return;
        }
        if (this.info.charFile == null) {
            return;
        }
        final File fDir = this.info.charFile.getParentFile();
        if (fDir == null) {
            return;
        }
        if (fDir.equals(fDirOld)) {
            try {
                final String name = this.info.charFile.getName();
                final String dir = fDirNew.getCanonicalPath() + GDConstants.FILE_SEPARATOR + name;
                final File f = new File(dir);
                this.info.charFile = f;
                if (this.info.gdChar != null) {
                    this.info.gdChar.setFileDir(fDirNew);
                }
                this.setChar(this.info);
            } catch (IOException ex) {
                GDMsgLogger.addError(ex);
            }
        }
    }

    public void setChar(final GDCharInfoList.GDCharFileInfo info) {
        this.info = info;
        this.uiTransfer.setChar(info);
        GDChar gdc = null;
        if (info != null) {
            gdc = info.gdChar;
        }
        if (gdc == null) {
            GDImagePool.buildCharStash(10, 18);
        } else {
            GDImagePool.buildCharStash(gdc.getStashWidth(), gdc.getStashHeight());
        }
        for (int i = 0; i < this.pnlPages.length; ++i) {
            this.pnlPages[i].setBGImage(GDImagePool.getCharStashBG());
            this.pnlPages[i].revalidate();
            this.pnlPages[i].repaint();
        }
        this.tabPages.revalidate();
        this.tabPages.repaint();
        this.layoutStash();
    }

    public GDContainerMapPane getCurrentPage() {
        final int index = this.tabPages.getSelectedIndex();
        return this.pnlPages[index];
    }

    public void layoutStash() {
        if (this.tabPages == null) {
            return;
        }
        GDChar gdc = null;
        if (this.info != null) {
            gdc = this.info.gdChar;
        }
        this.pnlPages[0].clearContainers();
        if (gdc != null) {
            final List<GDAbstractContainer> list = gdc.getStashPages();
            for (final GDAbstractContainer page : list) {
                final GDContainerPane container = new GDContainerPane(3, 97, 100, this.frame, this, this.uiTransfer);
                container.setContainer(page);
                this.pnlPages[0].addContainer(container);
            }
        }
        this.pnlPages[1].clearContainers();
        final GDUIContainer container2 = new GDEquippedContainerPane(19, 33, this.frame, this, this.uiTransfer);
        final GDUIContainer container3 = new GDContainerPane(4, 86, 485, this.frame, this, this.uiTransfer);
        if (gdc != null) {
            container2.setContainer(this.info.gdChar.getEquipment());
            container3.setContainer(this.info.gdChar.getInventory());
        }
        this.pnlPages[1].addContainer(container2);
        this.pnlPages[1].addContainer(container3);
        if (gdc == null) {
            this.buildBagContainer(null);
        } else {
            this.buildBagContainer(gdc);
        }
        this.tabPages.removeAll();
        this.tabPages.add(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_CHAR_STASH"), this.pnlPages[0]);
        this.tabPages.add(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_CHAR_INVENTORY"), this.pnlPages[1]);
        this.tabPages.add(GDMsgFormatter.getString(GDMsgFormatter.rbUI, "TXT_CHAR_BAGS"), this.pnlPages[2]);
    }

    private void buildBagContainer(final GDChar gdc) {
        List<GDCharInventorySack> sacks = null;
        if (gdc == null) {
            sacks = new LinkedList<GDCharInventorySack>();
        } else {
            sacks = gdc.getBags();
        }
        this.pnlPages[2].clearContainers();
        int i = 0;
        int x = 0;
        int y = 0;
        for (final GDCharInventorySack sack : sacks) {
            switch (i) {
                case 0: {
                    x = 15;
                    y = 0;
                    break;
                }
                case 1: {
                    x = 287;
                    y = 0;
                    break;
                }
                case 2: {
                    x = 15;
                    y = 261;
                    break;
                }
                case 3: {
                    x = 287;
                    y = 261;
                    break;
                }
                case 4: {
                    x = 15;
                    y = 521;
                    break;
                }
            }
            final GDUIContainer container = new GDContainerPane(5, x, y, this.frame, this, this.uiTransfer);
            container.setContainer(sack);
            this.pnlPages[2].addContainer(container);
            ++i;
        }
        while (i <= 4) {
            switch (i) {
                case 0: {
                    x = 15;
                    y = 0;
                    break;
                }
                case 1: {
                    x = 287;
                    y = 0;
                    break;
                }
                case 2: {
                    x = 15;
                    y = 261;
                    break;
                }
                case 3: {
                    x = 287;
                    y = 261;
                    break;
                }
                case 4: {
                    x = 15;
                    y = 521;
                    break;
                }
            }
            final GDUIContainer container2 = new GDContainerPane(5, x, y, this.frame, this, this.uiTransfer);
            container2.setContainer(null);
            this.pnlPages[2].addContainer(container2);
            ++i;
        }
    }

    public void deleteSelectedItem(final int action) {
        if (this.selItem == null) {
            return;
        }
        this.selPage.deleteItem(this.selItem, action, true);
        this.setSelectedItem(null);
    }

    public void moveSelectedItem(final int action, final int x, final int y) {
        if (this.selItem == null) {
            return;
        }
        final GDContainerMapPane page = this.getCurrentPage();
        final GDItem clone = this.selItem.clone();
        boolean success = page.addItem(clone, action, x, y);
        if (success) {
            success = this.selPage.deleteItem(this.selItem, action, true);
            if (success) {
                this.selItem = clone;
                this.selPage = page;
            }
        }
    }

    @Override
    public GDItem getSelectedItem() {
        return this.selItem;
    }

    @Override
    public void setSelectedItem(final GDItem item) {
        this.selItem = item;
        if (item == null) {
            this.selPage = null;
        } else {
            (this.selPage = this.getCurrentPage()).layoutContainers();
        }
        this.uiTransfer.setSelectedItem(item, 1);
    }

    public boolean addItem(final GDItem item, final int action, final int x, final int y) {
        if (item == null) {
            return false;
        }
        final GDContainerMapPane page = this.getCurrentPage();
        return page.addItem(item.clone(), action, x, y);
    }

    private class CharSelectActionListener implements ActionListener {
        @Override
        public void actionPerformed(final ActionEvent ev) {
            final int idx = GDCharStashPane.this.cbSelChar.getSelectedIndex();
            if (idx == -1) {
                return;
            }
            if (idx == 0) {
                GDCharStashPane.this.setChar(null);
                return;
            }
            int i = 1;
            for (final GDCharInfoList.GDCharFileInfo info : GDCharInfoList.gdCharFileInfos) {
                if (i == idx) {
                    if (info.gdChar == null) {
                        (info.gdChar = new GDChar(info.charFile)).read();
                    }
                    if (info.gdChar.hasErrors()) {
                        info.gdChar = null;
                    }
                    GDCharStashPane.this.setChar(info);
                    break;
                }
                ++i;
            }
            GDMsgLogger.showLog(GDCharStashPane.this, GDMsgFormatter.getString(GDMsgFormatter.rbUI, "ERRORS"));
        }
    }
}
